#include "PreCompile.h"
#include "Base/PluginGenerator.h"
#include "MicroCore.h"

GENERATE_PLUGIN(IMicroCore, MicroCore, MICRO_CORE_PLUGIN)

// Construct the Kernel
MicroCore::MicroCore() :
	m_strConfigFilePath(Directory::GetExcutableDirectory() + MICRO_CORE_NAME),
	m_pPluginManager(NULL),
	m_pThreadPool(NULL),
	m_iThreadPoolSize(8),
	m_bIsDebugMode(false),
	m_bDisposed(false)
{
	Initialize();
}

// Detructe the Kernel
MicroCore::~MicroCore()
{
	Destory();
}

// Init the Kernel 
None MicroCore::Initialize()
{
	// Configure the core
	MakeConfiguration();

	// Create thread pool
	CreateThreadPool();

	// Create plugin manager
	CreatePluginManager();
}

// Destory the Kernel
None MicroCore::Destory()
{
	if (!GetDisposed())
	{
		SetDisposed(true);

		// Destory plugin manager
		DestoryPluginManager();

		// Destory thread pool
		DestoryThreadPool();
	}
}

// Configure the core
bool MicroCore::MakeConfiguration()
{
	String strConfigFilePath = GetConfigFilePath();

	if (strConfigFilePath.IsEmpty())
	{
		return false;
	}

	String strErrorMsg = _T("");

	JsonDocument JsonDoc = JsonDocument::FromJsonFile(strConfigFilePath, strErrorMsg);

	if (JsonDoc.IsNull())
	{
		return false;
	}

	JsonDocument JsonObj = JsonDoc.GetKeyValue(_T("MicroCore"));

	Boolean bIsDebugMode = JsonObj.GetKeyValue(_T("SetDebugMode")).ToBool();

	SetIsDebugMode(bIsDebugMode);

	int iThreadPoolSize = JsonObj.GetKeyValue(_T("ThreadPoolSize")).ToInt();

	if (iThreadPoolSize < 3)
	{
		iThreadPoolSize = 3;
	}

	SetPoolSize(iThreadPoolSize);

	return true;
}

// Create plugin manager
void MicroCore::CreatePluginManager()
{
	m_ManagerLoader.Load(PLUGIN_MANAGER_NAME);

	IPluginManager* pManager = m_ManagerLoader.Data();

	SetPluginManager(pManager);
}

// Destory plugin manager
void MicroCore::DestoryPluginManager()
{

}

// Create thread pool
void MicroCore::CreateThreadPool()
{
	m_PoolLoader.Load(THREAD_POOL_NAME);

	IThreadPool* pPool = m_PoolLoader.Data();

	SetThreadPool(pPool);
}

// Destory thread pool
void MicroCore::DestoryThreadPool()
{

}

// Start thread pool
bool MicroCore::StartThreadPool()
{
	if (GetThreadPool() == NULL)
	{
		return false;
	}

	GetThreadPool()->Start(GetPoolSize());

	return true;
}

// Stop the thread pool
bool MicroCore::StopThreadPool()
{
	if (GetThreadPool() == NULL)
	{
		return false;
	}

	GetThreadPool()->Stop();

	return true;
}

// Start plugin manager
bool MicroCore::StartPluginManager()
{
	if (GetPluginManager() == NULL)
	{
		return false;
	}

	GetPluginManager()->SetPool(GetThreadPool());

	if (!GetPluginManager()->Start())
	{
		return false;
	}

	return true;
}

// Stop the plugin manager
bool MicroCore::StopPluginManager()
{
	if (GetPluginManager() == NULL)
	{
		return false;
	}

	if (!GetPluginManager()->Stop())
	{
		return false;
	}

	return true;
}

// Start main service
bool MicroCore::StartMainService()
{
	if (GetPluginManager())
	{
		if (!GetPluginManager()->StartMainService())
		{
			return false;
		}

		return true;
	}

	return false;
}

// Startup the micro core
bool MicroCore::Start()
{
	if (GetIsRunning())
	{
		return true;
	}

	SetIsRunning(true);

	// Start thread pool
	if (!StartThreadPool())
	{
		return false;
	}

	// Start the plugin manager
	if (!StartPluginManager())
	{
		return false;
	}

	// Start main service
	if (!StartMainService())
	{
		return false;
	}

	return true;
}

// Shutdown the micro core
bool MicroCore::Stop()
{
	if (!GetIsRunning())
	{
		return true;
	}

	SetIsRunning(false);

	// Stop the plugin manager
	StopPluginManager();

	// Stop the thread pool
	StopThreadPool();

	return true;
}

// Is core's debug mode
bool MicroCore::IsDebugMode()
{
	return GetIsDebugMode();
}

// Get the plugin by name and version
IPlugin* MicroCore::GetPlugin(std::string strPluginName,
	Int32 iMajorVersion,
	Int32 iMinorVersion,
	Int32 iModifyVersion)
{
	if (GetPluginManager())
	{
		return GetPluginManager()->GetPlugin(strPluginName,
			iMajorVersion,
			iMinorVersion,
			iModifyVersion);
	}

	return NULL;
}

// Add Task to the micro core
bool MicroCore::AddTask(Task& UserTask)
{
	if (GetThreadPool() == NULL)
	{
		return false;
	}

	TaskEntity InputTask;

	InputTask.strTaskId = UserTask.strTaskId;

	InputTask.strTaskName = UserTask.strTaskName;

	InputTask.iExcuteIntervalTimeMs = UserTask.iExcuteIntervalTimeMs;

	InputTask.bIsOneTimeTask = UserTask.bIsOneTimeTask;

	InputTask.pUserFunc = UserTask.pUserFunc;

	if (!GetThreadPool()->AddTask(InputTask))
	{
		return false;
	}

	return true;
}

// Pause the task
void MicroCore::PauseTask(std::string strTaskId)
{
	if (GetThreadPool())
	{
		GetThreadPool()->PauseTask(strTaskId);
	}
}

// Resume the task
void MicroCore::ResumeTask(std::string strTaskId)
{
	if (GetThreadPool())
	{
		GetThreadPool()->ResumeTask(strTaskId);
	}
}

// Stop the task
void MicroCore::StopTask(std::string strTaskId)
{
	if (GetThreadPool())
	{
		GetThreadPool()->StopTask(strTaskId);
	}
}
